/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Engine2D.renderer;

import Engine2D.graphics.GLColour;
import Engine2D.math.Vector2i;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;

/**
 *
 * @author Garys
 */
public class DefaultRenderer implements GLRenderer {
    
    /**
     * 
     */
    public int w;
    /**
     * 
     */
    public int h;
    private int depth;
    private GLColour colour;
    private Vector2i displayBounds;
    private boolean isFullScreen;
    
    
    
    private void createDisplay() {
        try {

            // Just in case it exists, destroy and reset display mode
            Display.destroy();
            
            
            try {
                DisplayMode modes[] = Display.getAvailableDisplayModes();
                int mode = -1;
                for (int i = 0; i < modes.length; i++) {
                    if (modes[i].getWidth() == w
                            && modes[i].getHeight() == h
                            && modes[i].getBitsPerPixel() >= depth) {
                        mode = i;
                        break;
                    }
                }
                
                if (mode != -1) {
                    System.out.println("Setting display mode to " + modes[mode]);
                    Display.setDisplayMode(modes[mode]);
                } else {
                    System.out.println("Setting display mode to " + modes[1]);
                    this.h = modes[1].getHeight();
                    this.w = modes[1].getWidth();
                    Display.setDisplayMode(modes[1]);
                }
                
                
            } catch (Exception e) {
                System.err.println("Failed to create display mode due to " + e);
            }

            // Now try to create display
            Display.create();
            Display.setTitle("hello");
            Display.setFullscreen(false);
            Display.setVSyncEnabled(false);
            
            displayBounds = new Vector2i(Display.getDisplayMode().getWidth(), Display.getDisplayMode().getHeight());
            
        } catch (LWJGLException ex) {
            //Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        
        
    }
    
    private void initGL(int w, int h) {
        // View aspects
        glViewport(0, 0, w, h);
        glMatrixMode(GLRenderer.GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, w, 0, h, -1, 1);
        
        
        glShadeModel(GLRenderer.GL_SMOOTH);
        glClearColor(0.0f, 0.7f, 0.0f, 0.5f); // Black Background
        glClearDepth(1.0f); // Depth Buffer Setup
        // GL11.glEnable(GL11.GL_DEPTH_TEST); // Enables Depth Testing
        glDepthFunc(GLRenderer.GL_LEQUAL); // The Type Of Depth Testing To Do
        glHint(GLRenderer.GL_PERSPECTIVE_CORRECTION_HINT, GLRenderer.GL_NICEST); // Really
        // Nice
        // Perspective
        // Calculations
        glEnable(GLRenderer.GL_TEXTURE_2D);

        // Transparency
        glBlendFunc(GLRenderer.GL_SRC_ALPHA, GLRenderer.GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GLRenderer.GL_BLEND);
    }
    
    /**
     * 
     * @param xsize
     * @param ysize
     */
    public void enterOrtho(int xsize, int ysize) {
		GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glLoadIdentity();
		GL11.glOrtho(0, w, h, 0, 1, -1);
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
		
		GL11.glTranslatef((w-xsize)/2,
						  (w-ysize)/2,0);
	}
    
    /**
     * 
     * @param width
     * @param height
     */
    public void initDisplay2(int width, int height) {
		this.w = width;
		this.h = height;
		
		//String extensions = GL11.glGetString(GL11.GL_EXTENSIONS);
		      System.out.println(GL11.GL_TEXTURE_2D);
		GL11.glEnable(GL11.GL_TEXTURE_2D);
		GL11.glShadeModel(GL11.GL_SMOOTH);        
		GL11.glDisable(GL11.GL_DEPTH_TEST);
		GL11.glDisable(GL11.GL_LIGHTING);                    
        
		GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);                
        GL11.glClearDepth(1);                                       
        
        GL11.glEnable(GL11.GL_BLEND);
        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
        
        GL11.glViewport(0,0,width,height);
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
	}
    
    /**
     * 
     * @param args
     */
    public static void main(String[] args) {
        
        DefaultRenderer render = new DefaultRenderer();
        
        render.initDisplay(800, 600);
        
        Random rand = new Random();
        while (true) {            
            try {
                Thread.sleep(0);
                Display.update();
                GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
                
                render.drawLine(rand.nextInt(800),rand.nextInt(600),rand.nextInt(800),rand.nextInt(600));
                
            } catch (InterruptedException ex) {
                Logger.getLogger(DefaultRenderer.class.getName()).log(Level.SEVERE, null, ex);
            }
            
        }
        
    }
    
    /**
     * 
     * @param w
     * @param h
     */
    @Override
    public void initDisplay(int w, int h) {
        this.w = w;
        this.h = h;
        this.colour = GLColour.WHITE;
        createDisplay();
        enterOrtho(0, 0);
        initDisplay2(this.w, this.h);
        //initGL(this.w, this.h);
        //setOrtho(this.w, this.h);
    }
    
    /**
     * 
     * @param xsize
     * @param ysize
     */
    @Override
    public void setOrtho(int xsize, int ysize) {
        glMatrixMode(GLRenderer.GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, w, h, 0, 1, -1);
        glMatrixMode(GLRenderer.GL_MODELVIEW);
        glTranslatef((w - xsize) / 2, (h - ysize) / 2, 0);
    }
    
    /**
     * 
     * @param xx
     * @param xy
     * @param yx
     * @param yy
     */
    public void drawLine(int xx, int xy, int yx, int yy) {
        glBlendFunc(GLRenderer.GL_SRC_ALPHA, GLRenderer.GL_ONE_MINUS_SRC_ALPHA);
        glColor4f(1f, 0f, 1f, 1f);
        glLineWidth(10f);
        glBegin(GLRenderer.GL_LINES);
        glVertex2i(xx, xy);
        glVertex2i(yx, yy);
        glEnd();
        
    }
    
    /**
     * 
     * @param xx
     * @param xy
     * @param yx
     * @param yy
     * @param width
     */
    public void drawLine(int xx, int xy, int yx, int yy, float width) {
        glBlendFunc(GLRenderer.GL_SRC_ALPHA, GLRenderer.GL_ONE_MINUS_SRC_ALPHA);
        glColor4f(1f, 0f, 1f, 1f);
        glLineWidth(width);
        glBegin(GLRenderer.GL_LINES);
        glVertex2i(xx, xy);
        glVertex2i(yx, yy);
        glEnd();
        
    }
    
    /**
     * 
     * @param geom
     */
    @Override
    public void glBegin(int geom) {
        GL11.glBegin(geom);
    }
    
    /**
     * 
     * @param target
     * @param texture
     */
    @Override
    public void glBindTexture(int target, int texture) {
        GL11.glBindTexture(target, texture);
    }
    
    /**
     * 
     * @param src
     * @param dest
     */
    @Override
    public void glBlendFunc(int src, int dest) {
        GL11.glBlendFunc(src, dest);
    }
    
    /**
     * 
     * @param bit
     */
    @Override
    public void glClear(int bit) {
        GL11.glClear(bit);
    }
    
    /**
     * 
     * @param red
     * @param green
     * @param blue
     * @param alpha
     */
    @Override
    public void glClearColor(float red, float green, float blue, float alpha) {
        GL11.glClearColor(red, green, blue, alpha);
    }
    
    /**
     * 
     * @param depth
     */
    @Override
    public void glClearDepth(float depth) {
        GL11.glClearDepth(depth);
    }
    
    /**
     * 
     * @param plane
     * @param buffer
     */
    @Override
    public void glClipPlane(int plane, DoubleBuffer buffer) {
        GL11.glClipPlane(plane, buffer);
    }
    
    /**
     * 
     * @param red
     * @param green
     * @param blue
     * @param alpha
     */
    @Override
    public void glColor4f(float red, float green, float blue, float alpha) {
        colour.set(red, green, blue, alpha);
        GL11.glColor4f(red, green, blue, alpha);
    }
    
    /**
     * 
     * @param func
     */
    @Override
    public void glDepthFunc(int func) {
        GL11.glDepthFunc(func);
    }
    
    /**
     * 
     * @param cap
     */
    @Override
    public void glDisable(int cap) {
        GL11.glDisable(cap);
    }
    
    /**
     * 
     * @param cap
     */
    @Override
    public void glEnable(int cap) {
        GL11.glEnable(cap);
    }
    
    /**
     * 
     */
    @Override
    public void glEnd() {
        GL11.glEnd();
    }
    
    /**
     * 
     * @param textures
     */
    @Override
    public void glGenTextures(IntBuffer textures) {
        GL11.glGenTextures(textures);
    }
    
    /**
     * 
     * @param target
     * @param mode
     */
    @Override
    public void glHint(int target, int mode) {
        GL11.glHint(target, mode);
    }
    
    /**
     * 
     * @param width
     */
    @Override
    public void glLineWidth(float width) {
        GL11.glLineWidth(width);
    }
    
    /**
     * 
     */
    @Override
    public void glLoadIdentity() {
        GL11.glLoadIdentity();
    }
    
    /**
     * 
     * @param mode
     */
    @Override
    public void glMatrixMode(int mode) {
        GL11.glMatrixMode(mode);
    }
    
    /**
     * 
     * @param x
     * @param y
     * @param z
     */
    @Override
    public void glNormal3f(float x, float y, float z) {
        GL11.glNormal3f(x, y, z);
    }
    
    /**
     * 
     * @param left
     * @param right
     * @param bottom
     * @param top
     * @param zNear
     * @param zFar
     */
    @Override
    public void glOrtho(double left, double right, double bottom, double top, double zNear, double zFar) {
        GL11.glOrtho(left, right, bottom, top, zNear, zFar);
    }
    
    /**
     * 
     */
    @Override
    public void glPushMatrix() {
        GL11.glPushMatrix();
    }
    
    /**
     * 
     */
    @Override
    public void glPopMatrix() {
        GL11.glPopMatrix();
    }
    
    /**
     * 
     * @param mode
     */
    @Override
    public void glShadeModel(int mode) {
        GL11.glShadeModel(mode);
    }
    
    /**
     * 
     * @param u
     * @param v
     */
    @Override
    public void glTexCoord2f(float u, float v) {
        GL11.glTexCoord2f(u, v);
    }
    
    /**
     * 
     * @param target
     * @param pname
     * @param param
     */
    @Override
    public void glTexParameterf(int target, int pname, float param) {
        GL11.glTexParameterf(target, pname, param);
    }
    
    /**
     * 
     * @param x
     * @param y
     * @param z
     */
    @Override
    public void glTranslatef(float x, float y, float z) {
        GL11.glTranslatef(x, y, z);
    }
    
    /**
     * 
     * @param x
     * @param y
     */
    @Override
    public void glVertex2f(float x, float y) {
        GL11.glVertex2f(x, y);
    }
    
    /**
     * 
     * @param x
     * @param y
     */
    @Override
    public void glVertex2i(int x, int y) {
        GL11.glVertex2i(x, y);
    }
    
    /**
     * 
     * @param x
     * @param y
     * @param z
     */
    @Override
    public void glVertex3f(float x, float y, float z) {
        GL11.glVertex3f(x, y, z);
    }
    
    /**
     * 
     * @param x
     * @param y
     * @param w
     * @param h
     */
    @Override
    public void glViewport(int x, int y, int w, int h) {
        GL11.glViewport(x, y, w, h);
    }

    /**
     * 
     * @param cap
     */
    @Override
    public void glEnableClientState(int cap) {
        GL11.glEnableClientState(cap);
    }

    /**
     * 
     * @param size
     * @param stride
     * @param pointer
     */
    @Override
    public void glColorPointer(int size, int stride, FloatBuffer pointer) {
        GL11.glColorPointer(size, stride, pointer);
    }

    /**
     * 
     * @param size
     * @param stride
     * @param pointer
     */
    @Override
    public void glTexCoordPointer(int size, int stride, FloatBuffer pointer) {
        GL11.glTexCoordPointer(size, stride, pointer);
    }

    /**
     * 
     * @param size
     * @param stride
     * @param pointer
     */
    @Override
    public void glVertexPointer(int size, int stride, FloatBuffer pointer) {
        GL11.glVertexPointer(size, stride, pointer);
    }

    /**
     * 
     * @param mode
     * @param first
     * @param count
     */
    @Override
    public void glDrawArrays(int mode, int first, int count) {
        GL11.glDrawArrays(mode, first, count);
    }

    /**
     * 
     */
    public void flush() {
	}

    
}
